home *** CD-ROM | disk | FTP | other *** search
- #include "bmapgfx.hpp"
-
- // Copyright (c) 1996 by Kerrigan Burgess, all rights reserved.
-
- BITMAPGFXCLASS::BITMAPGFXCLASS(void) // constructor.
- {
- Image=NULL;
- }
-
- BITMAPGFXCLASS::~BITMAPGFXCLASS(void) // destructor.
- {
- if (Image != NULL)
- delete Image;
- }
-
- void BITMAPGFXCLASS::Create( ImageStats *Stats, unsigned char *bitmap )
- {
- if (Image != NULL)
- delete Image;
- Image = new unsigned char [ Stats->size ];
- if (Image==NULL)
- Error("Not enough memory\n");
-
- Image = bitmap;
-
- MidX = Stats->width/2;
- MidY = Stats->height/2;
-
- Coords[0].x = 0-MidX;
- Coords[0].y = 0-MidY;
- Coords[1].x = 0-MidX;
- Coords[1].y = (Stats->height)-MidY;
- Coords[2].x = (Stats->width)-MidX;
- Coords[2].y = (Stats->height)-MidY;
- Coords[3].x = (Stats->width)-MidX;
- Coords[3].y = 0-MidY;
-
- Coords[0].u = 1;
- Coords[0].v = 1;
- Coords[1].u = 1;
- Coords[1].v = Stats->height-1;
- Coords[2].u = Stats->width-1;
- Coords[2].v = Stats->height-1;
- Coords[3].u = Stats->width-1;
- Coords[3].v = 1;
- }
-
- void BITMAPGFXCLASS::Scale(unsigned char *Buffer, float percentage)
- {
- int x0,y0,x2,y2;
-
- x0 = Coords[0].x*percentage + HALF_SCREEN_WIDTH;
- y0 = Coords[0].y*percentage + HALF_SCREEN_HEIGHT;
- x2 = Coords[2].x*percentage + HALF_SCREEN_WIDTH;
- y2 = Coords[2].y*percentage + HALF_SCREEN_HEIGHT;
-
- ScaleBitMap(x0,y0,x2,y2,
- Coords[0].u,Coords[0].v,Coords[2].u,Coords[2].v,
- Buffer,Image);
- }
-
- void BITMAPGFXCLASS::ScaleBitMap(int x0,int y0,int x2,int y2,
- int u0,int v0,int u2,int v2,
- unsigned char *Buffer,unsigned char *Image)
- {
- unsigned char *Source,*Dest;
- long LeftU,u,v,Du,Dv;
- int x,y,vint;
-
- // This is hard coded for 320x200.
-
- Du = ((u2-u0)<<16)/(x2-x0); // point 16 format.
- Dv = ((v2-v0)<<16)/(y2-y0);
- LeftU = u0<<16;
- v = v0<<16;
-
- if (y0 < _MinClipY)
- {
- v = v + (_MinClipY - y0)*Dv;
- y0 = _MinClipY;
- }
-
- if (y2 > _MaxClipY)
- y2 = _MaxClipY;
-
- if (x0 < _MinClipX)
- {
- LeftU = LeftU + (_MinClipX - x0)*Du;
- x0 = _MinClipX;
- }
-
- if (x2 > _MaxClipX)
- x2 = _MaxClipX;
-
- Buffer+=x0+(y0<<8)+(y0<<6);
-
- for (y=y0;y<y2;y++)
- {
- u=LeftU;
- vint=v>>16;
- Source=Image+(vint<<8)+(vint<<6);
- Dest=Buffer;
- for (x=x0;x<x2;x++)
- {
- *Dest++=Source[ u>>16 ];
- u+=Du;
- }
- v+=Dv;
- Buffer+=SCREENWIDTH;
- }
- }
-
- void BITMAPGFXCLASS::Rotate( unsigned char *Buffer, double angle, float scale)
- {
- float Cos, Sin, CosScale, CosAspectScale, SinAspect;
- static double ang=0;
- int x0,y0,x1,y1,x2,y2,x3,y3;
- int u0,v0,u1,v1,u2,v2,u3,v3;
-
- ang+=angle;
-
- angle = -ang*DEGREES_TO_RADIANS;
- Sin = (float)sin ( angle );
- Cos = (float)cos ( angle );
-
- x0 = Coords[0].x*Cos - Coords[0].y*Sin;
- y0 = Coords[0].x*Sin + Coords[0].y*Cos;
- x1 = Coords[1].x*Cos - Coords[1].y*Sin;
- y1 = Coords[1].x*Sin + Coords[1].y*Cos;
- x2 = Coords[2].x*Cos - Coords[2].y*Sin;
- y2 = Coords[2].x*Sin + Coords[2].y*Cos;
- x3 = Coords[3].x*Cos - Coords[3].y*Sin;
- y3 = Coords[3].x*Sin + Coords[3].y*Cos;
-
- x0=x0*scale+HALF_SCREEN_WIDTH;
- y0=y0*scale+HALF_SCREEN_HEIGHT;
- x1=x1*scale+HALF_SCREEN_WIDTH;
- y1=y1*scale+HALF_SCREEN_HEIGHT;
- x2=x2*scale+HALF_SCREEN_WIDTH;
- y2=y2*scale+HALF_SCREEN_HEIGHT;
- x3=x3*scale+HALF_SCREEN_WIDTH;
- y3=y3*scale+HALF_SCREEN_HEIGHT;
-
- u0=Coords[0].u;
- v0=Coords[0].v;
- u1=Coords[1].u;
- v1=Coords[1].v;
- u2=Coords[2].u;
- v2=Coords[2].v;
- u3=Coords[3].u;
- v3=Coords[3].v;
-
- RotateBitMap( x0,y0,x1,y1,x2,y2,
- u0,v0,u1,v1,u2,v2,
- Buffer, Image);
-
- RotateBitMap( x0,y0,x2,y2,x3,y3,
- u0,v0,u2,v2,u3,v3,
- Buffer, Image);
- }
-
- void BITMAPGFXCLASS::RotateBitMap(int x0,int y0,int x1,int y1,int x2,int y2,
- int u0,int v0,int u1,int v1,int u2,int v2,
- unsigned char *Buffer,unsigned char *Image)
- {
- long width, height,slope;
- long u,v,ScanU,ScanV,LeftU,LeftV,LeftDu,LeftDv;
- long LeftX,RightX,LeftDx,RightDx;
- long ClipLeftX,ClipRightX;
- int vint,x,y,newx,newu,newv,tempx,tempy,tempu,tempv,ydiff;
- int oldx2,oldy2,oldu2,oldv2;
- int GENERAL;
- unsigned char *Start;
-
- if (y1<y0) // switch. They're in the wrong order.
- {
- tempx=x0; tempy=y0;
- x0=x1; y0=y1;
- x1=tempx; y1=tempy;
-
- tempu=u0; tempv=v0;
- u0=u1; v0=v1;
- u1=tempu; v1=tempv;
- }
- if (y2<y0) // switch. They're in the wrong order.
- {
- tempx=x0; tempy=y0;
- x0=x2; y0=y2;
- x2=tempx; y2=tempy;
-
- tempu=u0; tempv=v0;
- u0=u2; v0=v2;
- u2=tempu; v2=tempv;
- }
- if (y2<y1) // switch. They're in the wrong order.
- {
- tempx=x1; tempy=y1;
- x1=x2; y1=y2;
- x2=tempx; y2=tempy;
-
- tempu=u1; tempv=v1;
- u1=u2; v1=v2;
- u2=tempu; v2=tempv;
- }
-
- GENERAL=FALSE; // reset cases (for Triangle).
- Start=Buffer; // save starting point of Buffer.
-
- if (y0==y1)
- goto FLAT_TOP;
- if (y1==y2)
- goto FLAT_BOTTOM;
- else
- GENERAL=TRUE;
-
- height = 65536/(y2-y0);
- slope = (x2-x0)*height;
- newx = x0+( (slope*(y1-y0))>>16 );
- newu = (((y1-y0)*u2+(y2-y1)*u0)*height)>>16;
- newv = (((y1-y0)*v2+(y2-y1)*v0)*height)>>16;
-
- oldx2 = x2; // save values for later.
- oldy2 = y2;
- oldu2 = u2;
- oldv2 = v2;
-
- x2 = newx;
- y2 = y1;
- u2 = newu;
- v2 = newv;
-
- FLAT_BOTTOM:
-
- if (x2<x1)
- {
- tempx=x2; x2=x1; x1=tempx;
- tempu=u2; u2=u1; u1=tempu;
- tempv=v2; v2=v1; v1=tempv;
- }
-
- height = 65536/(y2-y0); // fixed point 16.
- width = 65536/(x2-x1+1);
- LeftDx = (x1-x0)*height;
- RightDx = (x2-x0)*height;
- LeftDu = (u1-u0)*height;
- LeftDv = (v1-v0)*height;
-
- LeftX = x0<<16;
- RightX = LeftX + 32768; // 32768 is 0.5 fixed point 16
- LeftU = u0<<16;
- LeftV = v0<<16;
-
- ScanU = (u2-u1)*width; // constant across whole triangle.
- ScanV = (v2-v1)*width;
-
- if (y0 < _MinClipY)
- {
- ydiff = _MinClipY - y0;
- LeftX = LeftX+LeftDx*ydiff;
- RightX = RightX+RightDx*ydiff;
-
- LeftU = LeftU+LeftDu*ydiff;
- LeftV = LeftV+LeftDv*ydiff;
-
- y0 = _MinClipY;
- }
-
- if (y2 > _MaxClipY)
- y2 = _MaxClipY;
-
- Buffer+=(y0<<8)+(y0<<6);
-
- if (x0>=_MinClipX && x0<=_MaxClipX &&
- x1>=_MinClipX && x1<=_MaxClipX &&
- x2>=_MinClipX && x2<=_MaxClipX)
- {
- for (y=y0;y<y2;y++,Buffer+=SCREENWIDTH)
- {
- u=LeftU;
- v=LeftV;
- for (x=( LeftX>>16 );x<=( RightX>>16 );x++)
- {
- vint=v>>16;
- Buffer[x]=Image[ (u>>16)+(vint<<8)+(vint<<6) ];
- u+=ScanU;
- v+=ScanV;
- }
- LeftX += LeftDx;
- RightX += RightDx;
- LeftU += LeftDu;
- LeftV += LeftDv;
- }
- }
- else
- {
- for (y=y0;y<y2;y++,Buffer+=SCREENWIDTH)
- {
- ClipLeftX = LeftX>>16;
- ClipRightX = RightX>>16;
-
- u=LeftU;
- v=LeftV;
-
- if (ClipLeftX < _MinClipX)
- {
- if (ClipRightX < _MinClipX)
- {
- LeftX += LeftDx; // update the intensities and slopes.
- RightX += RightDx; // before continuing.
- LeftU += LeftDu;
- LeftV += LeftDv;
- continue;
- }
- u = LeftU + (_MinClipX - ClipLeftX)*ScanU;
- v = LeftV + (_MinClipX - ClipLeftX)*ScanV;
- ClipLeftX = _MinClipX; // the clipped amount.
- }
-
- if (ClipRightX > _MaxClipX)
- {
- if (ClipLeftX > _MaxClipX)
- {
- LeftX += LeftDx; // update the intensities and slopes.
- RightX += RightDx; // before continuing.
- LeftU += LeftDu;
- LeftV += LeftDv;
- continue;
- }
- ClipRightX = _MaxClipX;
- }
-
- for (x=ClipLeftX;x<=ClipRightX;x++)
- {
- vint=v>>16;
- Buffer[x]=Image[ (u>>16)+(vint<<8)+(vint<<6) ];
- u+=ScanU;
- v+=ScanV;
- }
- LeftX += LeftDx;
- RightX += RightDx;
- LeftU += LeftDu;
- LeftV += LeftDv;
- }
- }
-
- if (!GENERAL)
- return;
-
- x0 = x1; // setup for FLAT_TOP.
- y0 = y1;
- u0 = u1;
- v0 = v1;
-
- x1 = x2;
- u1 = u2;
- v1 = v2;
-
- x2 = oldx2;
- y2 = oldy2;
- u2 = oldu2;
- v2 = oldv2;
-
- Buffer = Start; // reset Buffer to starting point.
-
- FLAT_TOP:
-
- if (x1<x0)
- {
- tempx=x1; x1=x0; x0=tempx;
- tempu=u1; u1=u0; u0=tempu;
- tempv=v1; v1=v0; v0=tempv;
- }
-
- height = 65536/(y2-y0); // fixed point 16.
- width = 65536/(x1-x0+1);
-
- LeftDx = (x2-x0)*height; // Inverse left and right slope.
- RightDx = (x2-x1)*height;
- LeftDu = (u2-u0)*height;
- LeftDv = (v2-v0)*height;
-
- LeftX = x0<<16;
- RightX = (x1<<16)+32768; // 32768 is 0.5 fixed point 16.
- LeftU = u0<<16;
- LeftV = v0<<16;
-
- ScanU = (u1-u0)*width;
- ScanV = (v1-v0)*width;
-
- if (y0 < _MinClipY)
- {
- ydiff = _MinClipY - y0;
- LeftX = LeftX+LeftDx*ydiff;
- RightX = RightX+RightDx*ydiff;
-
- LeftU = LeftU+LeftDu*ydiff;
- LeftV = LeftV+LeftDv*ydiff;
-
- y0 = _MinClipY;
- }
-
- if (y2 > _MaxClipY)
- y2 = _MaxClipY;
-
- Buffer+=(y0<<8)+(y0<<6);
-
- if (x0>=_MinClipX && x0<=_MaxClipX &&
- x1>=_MinClipX && x1<=_MaxClipX &&
- x2>=_MinClipX && x2<=_MaxClipX)
- {
- for (y=y0;y<y2;y++,Buffer+=SCREENWIDTH)
- {
- u=LeftU;
- v=LeftV;
- for (x=( LeftX>>16 );x<=( RightX>>16 );x++)
- {
- vint=v>>16;
- Buffer[x]=Image[ (u>>16)+(vint<<8)+(vint<<6) ];
- u+=ScanU;
- v+=ScanV;
- }
- LeftX += LeftDx;
- RightX += RightDx;
- LeftU += LeftDu;
- LeftV += LeftDv;
- }
- }
- else
- {
- for (y=y0;y<y2;y++,Buffer+=SCREENWIDTH)
- {
- ClipLeftX = ( LeftX>>16 );
- ClipRightX = ( RightX>>16 );
-
- u=LeftU;
- v=LeftV;
-
- if (ClipLeftX < _MinClipX)
- {
- if (ClipRightX < _MinClipX)
- {
- LeftX += LeftDx; // update the intensities and slopes.
- RightX += RightDx; // before continuing.
- LeftU += LeftDu;
- LeftV += LeftDv;
- continue;
- }
- u = LeftU + (_MinClipX - ClipLeftX)*ScanU;
- v = LeftV + (_MinClipX - ClipLeftX)*ScanV;
- ClipLeftX = _MinClipX; // the clipped amount.
- }
-
- if (ClipRightX > _MaxClipX)
- {
- if (ClipLeftX > _MaxClipX)
- {
- LeftX += LeftDx; // update the intensities and slopes.
- RightX += RightDx; // before continuing.
- LeftU += LeftDu;
- LeftV += LeftDv;
- continue;
- }
- ClipRightX = _MaxClipX;
- }
-
- for (x=ClipLeftX;x<=ClipRightX;x++)
- {
- vint=(v>>16);
- Buffer[x]=Image[ (u>>16)+(vint<<8)+(vint<<6) ];
- u+=ScanU;
- v+=ScanV;
- }
- LeftX += LeftDx;
- RightX += RightDx;
- LeftU += LeftDu;
- LeftV += LeftDv;
- }
- }
- }
-